package org.smarthings.coap;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.californium.core.CoapResource;
import org.eclipse.californium.core.coap.CoAP.ResponseCode;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.eclipse.californium.core.server.resources.CoapExchange;
import org.smarthings.Message;
import org.smarthings.MessageBroker;
import org.smarthings.Response;
import org.smarthings.Utils;

public class CoapResourceImpl extends CoapResource {
	private static final MessageBroker broker = MessageBroker.getInstance();
	private List<String> changed = new ArrayList<String>();

	public CoapResourceImpl(String name) {
		super(name);
		setObservable(true);
	}

	public void handlePOST(CoapExchange exchange) {
		String contentType = MediaTypeRegistry.toString(exchange.getRequestOptions().getContentFormat());
		String uri = Utils.normalizeUri(exchange.getRequestOptions().getURIPathString());
		Response response = broker.post(Message.createSimpleMessage(exchange.getRequestPayload(), CoapFactory.PROTOCOL,
				uri, contentType));
		changed();
		exchange.respond(CoapUtil.getCoapCode(response.getCode(), ResponseCode.CHANGED), response.getPayload());
	}

	public void handleGET(CoapExchange exchange) {
		String source = exchange.getSourceAddress().toString() + exchange.getSourcePort();
		synchronized (changed) {
			if (changed.contains(source)) {
				exchange.respond(ResponseCode.CONTENT);
				return;
			} else {
				changed.add(source);
			}
		}

		int format = 0;
		String contentType = null;
		if (exchange.getRequestOptions().hasAccept()
				&& exchange.getRequestOptions().getAccept() != MediaTypeRegistry.UNDEFINED) {
			format = exchange.getRequestOptions().getAccept();
			contentType = MediaTypeRegistry.toString(format);
		}

		String uri = Utils.normalizeUri(exchange.getRequestOptions().getURIPathString());

		Message message = broker.get(uri, contentType);
		if (message == null) {
			exchange.respond(ResponseCode.NOT_FOUND);
			return;
		}

		format = MediaTypeRegistry.parse(message.getContentType());
		exchange.respond(ResponseCode.CHANGED, message.getPayload(), format);
	}

	public void changed() {
		synchronized (changed) {
			changed.clear();
		}
		super.changed();
	}
}
